package com.atguigu.gmall.item.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.item.service.ItemService;
import com.atguigu.gmall.list.client.ListFeignClient;
import com.atguigu.gmall.model.item.ItemVo;
import com.atguigu.gmall.model.product.*;
import com.atguigu.gmall.product.client.ProductFeignClient;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class ItemServiceImpl implements ItemService {

    //  需要远程调用service-product 的对象！
    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private ListFeignClient listFeignClient;


    @Override
    public ItemVo getItem(Long skuId) {

        //  创建一个ItemVo 对象
        ItemVo itemVo = new ItemVo();
        //  判断布隆过滤器中是否包含数据！
        //        RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter(RedisConst.SKU_BLOOM_FILTER);
        //        if (!bloomFilter.contains(skuId)){
        //            return itemVo;
        //        }

        //  多线程先去查询谁？ skuInfo , 因为后续的获取分类数据，还有销售属性数据等都需要skuInfo对象中的数据。
        CompletableFuture<SkuInfo> skuInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //  获取到 skuInfo
            SkuInfo skuInfo = this.productFeignClient.getSkuInfo(skuId);
            itemVo.setSkuInfo(skuInfo);
            return skuInfo;
        },threadPoolExecutor);

        // 获取分类数据 : 是否需要返回值 ，看获取到分类数据之后，categoryView 它做了什么事？ 直接放入itemVo 中。
        CompletableFuture<Void> categoryViewCompletableFuture = skuInfoCompletableFuture.thenAcceptAsync(skuInfo -> {
            BaseCategoryView categoryView = this.productFeignClient.getCategoryView(skuInfo.getCategory3Id());
            itemVo.setCategoryView(categoryView);
        },threadPoolExecutor);


        //  获取价格信息
        CompletableFuture<Void> skuPriceCompletableFuture = CompletableFuture.runAsync(() -> {
            BigDecimal skuPrice = this.productFeignClient.getSkuPrice(skuId);
            itemVo.setSkuPrice(skuPrice);
        },threadPoolExecutor);


        //  获取销售属性+锁定
        CompletableFuture<Void> spuSaleAttrCompletableFuture = skuInfoCompletableFuture.thenAcceptAsync(skuInfo -> {
            List<SpuSaleAttr> spuSaleAttrList = this.productFeignClient.getSpuSaleAttrListCheckBySku(skuId, skuInfo.getSpuId());
            itemVo.setSpuSaleAttrList(spuSaleAttrList);
        },threadPoolExecutor);

        //  获取切换功能数据 {在页面能够获取到用户点击的销售属性值Id， {"3724|3727":"24","3725|3727"|"23"}  }
        CompletableFuture<Void> strCompletableFuture = skuInfoCompletableFuture.thenAcceptAsync(skuInfo -> {
            Map skuValueIdsMap = this.productFeignClient.getSkuValueIdsMap(skuInfo.getSpuId());
            String strJson = JSON.toJSONString(skuValueIdsMap);
            itemVo.setValuesSkuJson(strJson);
        },threadPoolExecutor);


        //  获取商品的海报：
        CompletableFuture<Void> spuPosterCompletableFuture = skuInfoCompletableFuture.thenAcceptAsync(skuInfo -> {
            List<SpuPoster> spuPosterList = this.productFeignClient.getSpuPosterBySpuId(skuInfo.getSpuId());
            itemVo.setSpuPosterList(spuPosterList);
        },threadPoolExecutor);


        CompletableFuture<Void> attrCompletableFuture = CompletableFuture.runAsync(() -> {
            //  商品的规格参数 : 使用的是商品的平台属性代替了规格参数
            //  通过skuId  找对应的平台属性 iphone6s 64内存 玫瑰金 == 1001  1001 应该会有对应的平台属性！
            //  数据库表中 skuInfo = skuId = 24;
            List<BaseAttrInfo> attrList = this.productFeignClient.getAttrList(skuId);
            //  注意：商品的规格参数传递的数据格式： List<Map<String, String>>  List<BaseAttrInfo> 这两个数据格式不相符！
            //  数据格式不符：主要原因是因为页面渲染时需要的是 key - value 结构： attrName:平台属性名   attrValue：平台属性值名
            //  写拉姆达表达式的目的： List<BaseAttrInfo>  转换为 List<Map<String, String>>
            List<Map<String, String>> attrMapList = attrList.stream().map(baseAttrInfo -> {
                Map<String, String> hashMap = new HashMap<>();
                //  页面渲染时的key ： Thymeleaf item.html  ${attrName}    ${attrValue}
                //  分辨率：1920*1080(FHD)
                hashMap.put("attrName", baseAttrInfo.getAttrName());
                //  在这...  baseAttrInfo.getAttrValueList().get(0).getValueName()!
            /*
            ==>  Preparing: select bai.id, bai.attr_name, bav.id value_id, bav.value_name from base_attr_info bai inner join base_attr_value bav on bai.id = bav.attr_id inner join sku_attr_value ssav on ssav.value_id = bav.id where ssav.sku_id = ?
            ==> Parameters: 24(Long)
            <==    Columns: id, attr_name, value_id, value_name
            <==        Row: 106, 手机系统, 176, 安卓手机
            <==        Row: 107, 手机品牌, 177, 小米
            <==        Row: 23, 运行内存, 83, 8G
            <==        Row: 24, 机身内存, 82, 128G
             */
                hashMap.put("attrValue", baseAttrInfo.getAttrValueList().get(0).getValueName());
                return hashMap;
            }).collect(Collectors.toList());
            itemVo.setSkuAttrList(attrMapList);
        },threadPoolExecutor);

        //  获取远程调用 ： 热度排名
        CompletableFuture<Void> incrCompletableFuture = CompletableFuture.runAsync(() -> {
            this.listFeignClient.incrHotScore(skuId);
        }, threadPoolExecutor);

        //  多任务组合：
        CompletableFuture.allOf(
                skuInfoCompletableFuture,
                categoryViewCompletableFuture,
                skuPriceCompletableFuture,
                spuSaleAttrCompletableFuture,
                spuPosterCompletableFuture,
                strCompletableFuture,
                attrCompletableFuture,
                incrCompletableFuture).join();

        //  释放资源 attrCompletableFuture.isDone()  categoryViewCompletableFuture.isDone()
        //  skuPriceCompletableFuture.isDone()

        //  threadPoolExecutor.shutdown();
        //  返回数据
        return itemVo;
    }

}
